/*
Copyright (c) 2006 - 2008  Universitaet Osnabrueck, virtUOS
Authors: Markus Ketterl, Johannes Emden, Nils Schuhmacher, Andreas Rickling

This file is part of virtPresenter.

virtPresenter is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

virtPresenter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with virtPresenter.  If not, see <http://www.gnu.org/licenses/>.
*/

package virtPresenter.model
{
	import com.adobe.cairngorm.control.CairngormEventDispatcher;
	
	import flash.display.*;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.filters.*;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.text.*;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	
	import mx.core.Application;
	import mx.core.FlexGlobals;
	import mx.core.UIComponent;
	
	import virtPresenter.event.MainWindowPreviewEvent;
	import virtPresenter.event.SpeedareaScrollEvent;
	import virtPresenter.event.VideoPlayerTimeChangeEvent;
	
	/**
	 * Creates the advanced scrubber.
	 */
	public class AdvancedScrubber extends UIComponent
	{	
	   public static var durationLabel:TextField;
	   
       public var actualWidth:Number;		
	   private var duration:Number;
	   private var thumbSmallCurrentY:Number; 
	   private var oldXPosition:Number;
	   private var controlPosition:Number;
	   private var lastWidth:Number=1; 
	   private var leftDrawBorder:int;
	   private var rightDrawBorder:int;
	   private var currentYVideoPosLine:int;
	   private var currentXVideoPosLine:int;
	   private var newTime:Number;
	   
	   private var thumb:Sprite;
	   private var thumbSmall:Sprite = new Sprite();
	   private var history_rectangle:Sprite;
	   private var baseTrack:Sprite; 
	        
       private var scrubbing:Boolean=false;
	   private var standardNavigation:Boolean=false;
       private var thumbSmallGrabbed:Boolean = false;     
	   private var userAction:Boolean = false;
       
	   private var xPosOfSlideSteps: Array = new Array();
	   public var lv:Array;
	   private var slideSteps:Array;
	   public var animStepsXPos:Array = new Array();
   
	   private static var speedScrubTimer:Timer = new Timer(500,1);
	   private var animationLines:AnimationReferenceLines;
	   private var t:TimeCode = new TimeCode;
	   private var miniFisheyes:MiniPreview;
       private var locator:virtPresenterLocator=virtPresenterLocator.getInstance();		
    	
    	/**
    	 * Constructs the scrubber with the given width.
    	 * 
    	 * @parameters width Width of the scrubber
    	 */   			 
        public function AdvancedScrubber(width:Number)
        {
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
            var format:TextFormat = new TextFormat();
			format.font = "Arial";
			format.color = 0x000000;
			format.size = 12;
			format.bold = true;
			format.underline = false;
            locator.toolTip = new TextField();
            locator.toolTip.text="Titel ";
			locator.toolTip.defaultTextFormat = format;
            locator.toolTip.x=0;
            locator.toolTip.y=-23;
            locator.toolTip.autoSize=TextFieldAutoSize.LEFT;
            locator.toolTip.mouseEnabled=false;
            locator.toolTip.visible=false;
   			locator.toolTip.background=true;
            durationLabel = new TextField();
            durationLabel.text="Gesamtzeit";
			durationLabel.defaultTextFormat = format;
			durationLabel.autoSize=TextFieldAutoSize.RIGHT;
            durationLabel.x=width-durationLabel.width;
            durationLabel.y=AS_Constants.SCRUBBER_HEIGHT;            
            if(baseTrack!=null) this.removeChild(baseTrack);
		    baseTrack = new Sprite();
			baseTrack.addChild(durationLabel);
            var borderTrack:Sprite = new Sprite();
		    borderTrack.graphics.lineStyle(1,AS_Constants.BORDER_COLOR);
		    borderTrack.graphics.beginFill(0xFFFFFF);
			borderTrack.graphics.drawRect(0, 0,width-2, AS_Constants.SCRUBBER_HEIGHT); 		    	
			this.addChild(baseTrack);
			FisheyeWindow.getInstance().initializeFisheyes(this);	
			speedScrubTimer.addEventListener(TimerEvent.TIMER, speedScrubHandler);
			controlPosition = 0.48;
        }
       
       	/**
       	 * Redraws the scrubber with the current width.
       	 */
	    public function redraw():void{
	    	draw(this.lastWidth);
	    }
	       	   
		/**
		 * Draws the scrubber with the given width.
		 * 
		 * @parameters width Width of the scrubber
		 */       
		public function draw(width:Number):void
	    {  	
	    	this.lastWidth = width;
	    	this.scrubbing = false
	    	this.actualWidth=width;
		    
		    if(baseTrack!=null) this.removeChild(baseTrack);
		    
		    baseTrack = new Sprite();
	     	
	     	if(locator.metaData!=null)
	     	{
		      	durationLabel.text=t.getTC(locator.metaData.duration);
		        durationLabel.x=width+60;
	            durationLabel.y=AS_Constants.SCRUBBER_HEIGHT-durationLabel.height+7;
	    	}	      	 	
	      	 	 	
		 	var borderTrack:Sprite = new Sprite();
		    borderTrack.graphics.lineStyle(3,AS_Constants.BORDER_COLOR);    // Frame; orange was: ff8040 
		    borderTrack.graphics.beginFill(AS_Constants.MOUSEOFFTRACK_COLOR);
		   
			borderTrack.graphics.drawRect(0, 0,width-2, AS_Constants.SCRUBBER_HEIGHT); 
	        
		    slideSteps = locator.xmlParser.getSlides();
			
		    if(this.thumb!=null)  this.thumb.graphics.clear();
		    
		    initializeHistoryRectangle(borderTrack);
			
			animStepsXPos = AS_Math.calculateAnimStepsXCoordiantes(this.lastWidth);
			
			for(var j:int=0;j<slideSteps.length;j++)
			{
				var tmp:TimeStep = slideSteps[j];
				var currentPosition:Number = (tmp.getTime() / 1000)/ (this.duration);
				var tmpTrack:Sprite = new Sprite();
				tmpTrack.alpha=0.75;
				tmpTrack.graphics.lineStyle(1,AS_Constants.LINES_COLOR);
				
				var matrix:Matrix = new Matrix();
				matrix.createGradientBox(20,300,0,0,0);
				var rotation:Number = Math.PI/2; 
				matrix.rotate(rotation);
				
				tmpTrack.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF,0x000000], [0,100], [0,255], matrix, null, InterpolationMethod.RGB);
				tmpTrack.graphics.beginFill(AS_Constants.MOUSEOFFTRACK_COLOR);
				
				var xpos:int=width*currentPosition;
				xPosOfSlideSteps[j]=xpos;
				var trackWidth:int=width-xpos-2;
				 //for the last track; goes until end of picture
				if(j+1<slideSteps.length)
				{
					var tmpTimeStep:TimeStep = slideSteps[j+1];
					var psWidth:Number= (tmpTimeStep.getTime() / 1000)/ (this.duration);
					trackWidth=(width*psWidth)-xpos;
				}					
				tmpTrack.graphics.drawRect(0, 0,trackWidth, AS_Constants.SCRUBBER_HEIGHT)
				tmpTrack.x=xpos;
				tmpTrack.addEventListener(MouseEvent.MOUSE_OVER, mouseOverScrubber);
				tmpTrack.addEventListener(MouseEvent.MOUSE_OUT, mouseOutScrubber);
				tmpTrack.addEventListener(MouseEvent.CLICK,handleClickOnScrubber);				
				borderTrack.addChild(tmpTrack);
			}	
			
			baseTrack.addChild(durationLabel);
		    baseTrack.addChild(borderTrack);
			this.addChild(baseTrack);
			this.animationLines = new AnimationReferenceLines(this);
			this.thumb = new Sprite();
			this.thumb.addChild(thumbSmall); //new
           	this.thumb.graphics.beginFill(0x888888);           	
			this.thumb.graphics.lineStyle(2,AS_Constants.DRAGGER_BORDER_COLOR);
			this.thumb.alpha=0.6;
			Speedareas.getInstance().setParent(this);
        	this.addChild(this.thumb);
			
			this.miniFisheyes = new MiniPreview();
			handleScrub(this.thumb);
  			borderTrack.addChild(locator.toolTip); 
			AS_Constants.PARKING_POSITION_X_THUMB_SMALL = this.thumb.x;
			this.drawThumbSmall(AS_Constants.PARKING_POSITION_X_THUMB_SMALL,(AS_Constants.SCRUBBER_HEIGHT/2));
			
			thumbSmall.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDownThumbSmall);
			thumb.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDownThumbSmall);
			FlexGlobals.topLevelApplication.addEventListener(MouseEvent.MOUSE_UP, handleMouseUpThumbSmall);
		}    	
		
		private function isFirstAnimationStep():Boolean{
			return this.thumb.x<animStepsXPos[1];
		}
		
		private function isLastAnimationStep():Boolean{
			return this.thumb.x>animStepsXPos[animStepsXPos.length-2];
		}
		
		private function mouseOutScrubber(e:MouseEvent):void{
			locator.toolTip.visible=false;
			var oldWidth:int= e.target.width;
			var oldX:int= e.target.x;
			e.target.graphics.clear();
			e.target.alpha=0.75;
			e.target.graphics.lineStyle(1,AS_Constants.LINES_COLOR);	        	
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(20,300,0,0,0);
			var rotation:Number = Math.PI/2; 
			matrix.rotate(rotation);
			e.target.graphics.beginFill(AS_Constants.MOUSEOFFTRACK_COLOR);
			e.target.graphics.drawRect(0, 0,oldWidth-1, AS_Constants.SCRUBBER_HEIGHT);
		}
		
		private function mouseOverScrubber(e:MouseEvent):void{
			var oldWidth:int= e.target.width;
			var oldX:int= e.target.x;
			e.target.graphics.clear();		
			e.target.alpha=0.75;
			e.target.graphics.lineStyle(1,AS_Constants.LINES_COLOR);
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(20,300,0.1,0,0);
			var rotation:Number = Math.PI/2; 
			matrix.rotate(rotation);
			e.target.graphics.beginGradientFill(GradientType.LINEAR, [0xBBBBFF,0xFFFFFF], [50,100], [0,255], matrix, null, InterpolationMethod.RGB);
			e.target.graphics.drawRect(0, 0,oldWidth-1, AS_Constants.SCRUBBER_HEIGHT);
			var time:Number = (locator.metaData.duration *((e.target.x+1)/actualWidth))*1000;			           		
			if(!scrubbing)
			{
				locator.toolTip.text=""+locator.xmlParser.getTimeStepByTime(time).getTitle();
				locator.toolTip.border=true;
				locator.toolTip.x=e.target.x+(e.target.width/2)-(locator.toolTip.width/2);
				if(locator.toolTip.x<0) locator.toolTip.x=-20;
				else if(locator.toolTip.x+locator.toolTip.width>locator.scrubber.actualWidth)
					locator.toolTip.x=locator.scrubber.actualWidth-locator.toolTip.width+20;				           	
				locator.toolTip.visible=true;
			} 
		}
		
		private function handleMouseDownThumbSmall(e:MouseEvent):void{
			this.thumbSmallGrabbed = true;
		}
		
		private function handleMouseUpThumbSmall(e:MouseEvent):void{
			var time:Number;
			if (this.isEnhancedNavigation())
				time = newTime;
			else
				time = this.duration * (this.thumb.x / actualWidth);
			this.thumbSmallGrabbed = false;
			this.scrubbing=false;
			this.thumb.stopDrag();	
			changeVideoPosition(time);
		}
		
		public function changeVideoPosition(time:Number):void{
			userAction = true;
			controlPosition = time;
			locator.netStream.seek(time);
			CairngormEventDispatcher.getInstance().dispatchEvent(new VideoPlayerTimeChangeEvent(time));	
		}
		
		private function thumbLeavesConstraints(y:int):Boolean{
			if (y<(AS_Constants.SCRUBBER_HEIGHT/2) 
					|| y> AS_Constants.SCRUBBER_HEIGHT
					      +this.distanceScrubberToPreview()
						  +AS_Constants.getPreviewHeight(this.thumb.x,lv))
			{
				return true;	
			}
			
			if (this.isEnhancedNavigation()){
				var point:Number =AS_Math.calculateBorderLineXPos(thumbSmall.mouseY-AS_Constants.SCRUBBER_HEIGHT,lv[0],(thumb.x-200-this.calculatePreviewPosition()));
				if ((thumb.x+thumbSmall.mouseX)<point) 
					return true;
				point = AS_Math.calculateBorderLineXPos(thumbSmall.mouseY-AS_Constants.SCRUBBER_HEIGHT,lv[1],(thumb.x+200-this.calculatePreviewPosition()));
				if ((thumb.x+thumbSmall.mouseX)>point) 
					return true;
			}
			return false;
		}
		
		private function drawThumbSmall(x:int, y:int):void{
			if (thumbLeavesConstraints(y)) return;
			this.thumbSmall.graphics.clear();	
			this.thumbSmall.graphics.beginFill(0x1f628c);   
			this.thumbSmall.graphics.drawCircle(x,y,5);
		}
        
        /**
         * Handles a roll over event of the thumb (dragger).
         */
        private function handleRollOverThumb(e:MouseEvent):void
        {
        	var sprite:Sprite = e.target as Sprite;
        	sprite.graphics.clear();
        	sprite.alpha=1;
           	sprite.graphics.beginFill(0x888888);   // Color, when mousepointer over thumb
          	sprite.graphics.lineStyle(2,AS_Constants.DRAGGER_BORDER_COLOR);        
           	handleScrub(sprite); 
        }
        
        /**
         * Handles a roll out event of the thumb (dragger).
         */
        public function handleRollOutThumb(e:MouseEvent):void
        {
        	var sprite:Sprite = e.target as Sprite;
        	sprite.graphics.clear();
        	sprite.alpha=0.6;
           	sprite.graphics.beginFill(0x888888);  // Color, when mousepointer leaves thumb
            sprite.graphics.lineStyle(2,AS_Constants.DRAGGER_BORDER_COLOR);         
            handleScrub(sprite);
        }
		
		private function drawThumb():void{
			this.thumb.graphics.beginFill(0x87cefa);   
			this.thumb.graphics.lineStyle(3,0x5f9ea0);
			this.thumb.graphics.drawCircle(0,AS_Constants.SCRUBBER_HEIGHT/2,AS_Constants.DRAGGER_SIZE);	
		}
        
		private function doStandardNavigation(y:Number):void{
			this.standardNavigation=true;
			this.thumb.startDrag(false, new Rectangle(0, 0, this.actualWidth, 0));
			this.drawThumbSmall(AS_Constants.PARKING_POSITION_X_THUMB_SMALL,y);
		}
		
		public function distanceScrubberToPreview():int{
			if (this.thumb.x>=lv[2] && this.thumb.x<lv[3]){
				return AS_Constants.DISTANCE_PREVIEW_MIDDLE_TO_SCRUBBER;
			} else if ((this.thumb.x>lv[3] && this.thumb.x<lv[1]) 
				|| (this.thumb.x<lv[2] && this.thumb.x>lv[0])){
				return AS_Constants.DISTANCE_PREVIEW_SIDES_TO_SCRUBBER;
			} else if (this.thumb.x<lv[0] || this.thumb.x>lv[1]){
				return AS_Constants.DISTANCE_PREVIEW_SIDES_TO_SCRUBBER;
			}
			return 0;
		}

		private function doEnhancedNavigation(y:Number):void{
			this.standardNavigation=false;
			this.thumb.stopDrag();
			var diffToStart:int = this.thumb.mouseX;
			var yPaint:Number = y;
			if (y>AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview()){
				y=AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview();
			}
			if (thumbInSpeedarea()){
				speedScrubTimer.start();
			} else if (thumbInMiddlePreviewArea()){
				var leftAnchorPoint: int =this.thumb.x -70-calculatePreviewPosition();
				var rightAnchorPoint: int = this.thumb.x + 70 -calculatePreviewPosition();
				this.redrawThumb(AS_Math.calculateNewThumbPosition(this.thumb.x, diffToStart, y, lv[2], lv[3], leftAnchorPoint, rightAnchorPoint));	
				newTime = calculatePreciseTime(lv[2],leftAnchorPoint,lv[3],rightAnchorPoint, diffToStart,y);
			} else if (thumbInRightPreviewArea()){
				leftAnchorPoint = this.thumb.x +70-calculatePreviewPosition();
				rightAnchorPoint = this.thumb.x + 200 -calculatePreviewPosition();
				this.redrawThumb(AS_Math.calculateNewThumbPosition(this.thumb.x, diffToStart, y, lv[3], lv[1], leftAnchorPoint, rightAnchorPoint));		
				newTime = calculatePreciseTime(lv[3],leftAnchorPoint,lv[1],rightAnchorPoint, diffToStart,y);
			} else if (thumbInLeftPreviewArea()){
				leftAnchorPoint = this.thumb.x - 200-calculatePreviewPosition();
				rightAnchorPoint = this.thumb.x - 70 -calculatePreviewPosition();
				this.redrawThumb(AS_Math.calculateNewThumbPosition(this.thumb.x, diffToStart, y, lv[0], lv[2], leftAnchorPoint, rightAnchorPoint));	
				newTime = calculatePreciseTime(lv[0],leftAnchorPoint,lv[2],rightAnchorPoint, diffToStart,y);
			} 
			
			this.drawThumbSmall(diffToStart,yPaint);
			if (!thumbInSpeedarea())
				durationLabel.text=" "+t.getTC(newTime)+"/"+ t.getTC(locator.metaData.duration);
		}
		
		private function calculatePreciseTime(leftLine:int, leftAnchorPoint:int, rightLine:int, rightAnchorPoint:int, newX:int,y:int):Number{
			var i:int = 0; 
			while (animStepsXPos[i]>leftLine){
				 i++;
			 }
			var t:TimeStep = locator.xmlParser.timeSteps[i];
			var baseTime:Number = t.getTime();
			
			var timeInX:Number = this.thumb.x + AS_Math.calculateNewThumbPositionPrecise(this.thumb.x,newX,y,leftLine,rightLine,leftAnchorPoint,rightAnchorPoint);
			return this.duration * (timeInX / actualWidth);
		}

		private function speedScrubHandler(evt:TimerEvent):void{
			Speedareas.getInstance().speedScrub();
			updateScrubber();
			lv = AS_Math.calculateAnimLineValues(thumb.x,animStepsXPos,actualWidth);
			speedScrubTimer.stop();
		}
		
		private function thumbInMiddlePreviewArea():Boolean{
			return this.thumb.x>lv[2] && this.thumb.x<lv[3];
		}
		
		private function thumbInRightPreviewArea():Boolean{
			return this.thumb.x>lv[3] && this.thumb.x<lv[1];
		}
		
		private function thumbInLeftPreviewArea():Boolean{
			return this.thumb.x<lv[2] && this.thumb.x>lv[0];
		}
		
		private function thumbInSpeedarea():Boolean{
			Speedareas.getInstance().setActivationOnCoordinates(this.mouseX, this.mouseY);
			return Speedareas.getInstance().activeSpeedareaPresent();
		}
		
		private function redrawThumb(x:int):void{	
			if (this.thumb.x+x<=lv[0])
				this.thumb.x = lv[0]+1;
			else if (this.thumb.x+x>=lv[1])
				this.thumb.x = lv[1]-1;
			else
				this.thumb.x += x;
		}
				     
        public function handleScrub(thumb:Sprite):void       
        {      
			if (!this.isEnhancedNavigation() && !FisheyeWindow.getInstance().getPreviewMode()) {
				lv = AS_Math.calculateAnimLineValues(this.thumb.x,animStepsXPos,this.actualWidth);
			}
			if (!this.isEnhancedNavigation() && !Speedareas.getInstance().activeSpeedareaPresent()){
				oldXPosition = this.thumb.x;
			}
				
			if (this.thumbSmallGrabbed){
				this.scrubbing = true;
				if (thumbSmall.mouseY<AS_Constants.SCRUBBER_HEIGHT)
					doStandardNavigation(thumbSmall.mouseY);
				else{
					if (standardNavigation) oldXPosition = this.thumb.x;
					doEnhancedNavigation(thumbSmall.mouseY);
				}	
			}
			else
				drawThumbSmall(AS_Constants.PARKING_POSITION_X_THUMB_SMALL,AS_Constants.SCRUBBER_HEIGHT/2);
			drawPreviewArea();
			drawThumb();      	     	
        }
       
		public function isStandardNavigation():Boolean{
			return standardNavigation;
		}
		
		private function isEnhancedNavigation():Boolean{
			return !this.standardNavigation && this.scrubbing;
		}
		
		public function calculatePreviewPosition():int{
			if (this.isEnhancedNavigation() || Speedareas.getInstance().activeSpeedareaPresent()){
				return thumb.x-oldXPosition;
			}
			else
				return 0;
		}
        
        public function drawPreviewArea():void{
			this.animationLines.setX(this.thumb.x);
			this.animationLines.setY(this.thumb.y);
			this.animationLines.drawReferenceLiness(lv,calculatePreviewPosition(),
				this.isFirstAnimationStep(), this.isLastAnimationStep());
			FisheyeWindow.getInstance().drawFisheyes(this.thumb.x,calculatePreviewPosition(), 
				!this.isFirstAnimationStep(), !this.isLastAnimationStep());
			Speedareas.getInstance().redraw(!this.isFirstAnimationStep(), !this.isLastAnimationStep(),this.thumb);
        	drawVideoPositionLine();
			miniFisheyes.showMiniSlides(!isFirstAnimationStep(),!isLastAnimationStep(),this,this.thumb.x);
		}
		
		//TODO: REFACTORN!!!!
		private function drawVideoPositionLine():void{
			if (FisheyeWindow.getInstance().getPreviewMode()) return;
			this.thumb.graphics.beginFill(0x87cefa);   
			this.thumb.graphics.lineStyle(3,0x5f9ea0);
			this.thumb.graphics.moveTo(0,AS_Constants.SCRUBBER_HEIGHT/2+6); 
			this.thumb.graphics.lineTo(0,AS_Constants.SCRUBBER_HEIGHT);
			var distanceScrubberToPreview:int = distanceScrubberToPreview();
			if (this.isStandardNavigation() || !scrubbing){
				var	xGoal:int = (((this.thumb.x-lv[2])/(lv[3]-lv[2]))*AS_Constants.WIDTH_PREVIEW_MIDDLE)-(AS_Constants.WIDTH_PREVIEW_MIDDLE/2)- calculatePreviewPosition();
				this.thumb.graphics.moveTo(0,AS_Constants.SCRUBBER_HEIGHT);
				this.thumb.graphics.lineTo(xGoal,AS_Constants.SCRUBBER_HEIGHT + distanceScrubberToPreview);
			}
			if (this.isEnhancedNavigation()){	
				var rise:Number;	
				var goalX:int = this.thumbSmall.mouseX;

				if (thumbLeavesConstraints(this.thumbSmall.mouseY)){
					if (this.thumbSmall.mouseX>0){
						goalX = AS_Math.calculateBorderLineXPos(thumbSmall.mouseY-AS_Constants.SCRUBBER_HEIGHT,lv[1],(thumb.x+200-this.calculatePreviewPosition()));
					}
					else{
						goalX = AS_Math.calculateBorderLineXPos(thumbSmall.mouseY-AS_Constants.SCRUBBER_HEIGHT,lv[0],(thumb.x-200-this.calculatePreviewPosition()));
					}
					goalX = goalX-this.thumb.x;
				}	
				
				if (thumbSmall.mouseY>AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview)
					rise = AS_Math.riseOnLinearEquation(goalX,0, distanceScrubberToPreview,0);
				else
					rise = AS_Math.riseOnLinearEquation(goalX,0, thumbSmall.mouseY,AS_Constants.SCRUBBER_HEIGHT);
				
				var goal:Number = AS_Math.calculateValueOfLinearEquation(distanceScrubberToPreview,rise);
				
				if (this.mouseX<Speedareas.getInstance().getSpeedareaLeftX()
						&& this.thumbSmall.mouseY>=AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview) goal = (this.thumb.x-Speedareas.getInstance().getSpeedareaLeftX())*(-1);
				if (this.mouseX>Speedareas.getInstance().getSpeedareaRightX()
						&& this.thumbSmall.mouseY>=AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview) goal  = Speedareas.getInstance().getSpeedareaRightX()-this.thumb.x;
				
				this.thumb.graphics.moveTo(0,AS_Constants.SCRUBBER_HEIGHT); 
				this.thumb.graphics.lineTo(goal,AS_Constants.SCRUBBER_HEIGHT + distanceScrubberToPreview);
				currentXVideoPosLine = goalX;
				
				if (this.thumbSmall.mouseY>=AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview){
					var goalY:int = this.thumbSmall.mouseY;
					if (this.thumbLeavesConstraints(this.thumbSmall.mouseY)){
						goalY = currentYVideoPosLine;
					}
					this.thumb.graphics.moveTo(goal, AS_Constants.SCRUBBER_HEIGHT+distanceScrubberToPreview);
					this.thumb.graphics.lineTo(goal, goalY);
					currentYVideoPosLine = goalY;
				}	
			}
		}
		
        /**
         * Handles the event when the user clicks somewhere in the scrubber. 
         */
        public function handleClickOnScrubber(e:MouseEvent):void
        {	
			var newX:Number = e.target.x+1;
			this.thumb.x = newX;
			var time:Number = (newX / actualWidth) * this.duration;
			this.changeVideoPosition(time);
			this.scrubbing = false;
        }        
        
        /**
         * Sets the duration.
         * 
         * <p>The duration is a value for the duration of the video. The scrubber needs
         * the information of the video duration the calculate the length of the tracks</p> 
         */                    
        public function setDuration(dur:Number):void{
        	this.duration = dur;
        }
		
		public function checkUserAction():void{
			if (userAction){			
				if (int(controlPosition) == int(locator.netStream.time)
					|| Math.round(controlPosition) == Math.round(locator.netStream.time)){
					userAction = false;
				}
			}
		}
		
		public function updateScrubber():void{
			CairngormEventDispatcher.getInstance().dispatchEvent(new VideoPlayerTimeChangeEvent(locator.netStream.time));
			this.thumb.x =((locator.currentvideotime/ this.duration)*actualWidth);
		}
		
		public function scrubbingActions():void{
			if (this.isEnhancedNavigation()){
				if (this.thumb.x>lv[3])
					CairngormEventDispatcher.getInstance().dispatchEvent(new MainWindowPreviewEvent(MainWindowPreviewEvent.NEXT));
				else if (this.thumb.x<lv[2])
					CairngormEventDispatcher.getInstance().dispatchEvent(new MainWindowPreviewEvent(MainWindowPreviewEvent.PREV));
				else
					CairngormEventDispatcher.getInstance().dispatchEvent(new MainWindowPreviewEvent(MainWindowPreviewEvent.CURR));
			} 
			checkUserAction();
			if (userAction) {
				locator.netStream.seek(controlPosition);
				return;
			}
			if(!this.scrubbing)
			{
				updateScrubber();   
			} 
			else if (this.isStandardNavigation()){
				var time:int = this.duration * (this.thumb.x) / actualWidth;
				CairngormEventDispatcher.getInstance().dispatchEvent(new VideoPlayerTimeChangeEvent(time));
			}
		}
		
		private function drawHistoryRectangle():void{
			this.history_rectangle.width=this.thumb.x;
		}
		
		private function initializeHistoryRectangle(sprite:Sprite):void{
			this.history_rectangle= new Sprite();	
			this.history_rectangle.graphics.beginFill(AS_Constants.HISTORY_COLOR);   // History Color F4A460
			this.history_rectangle.graphics.drawRect(0,0,1, AS_Constants.SCRUBBER_HEIGHT);
			this.history_rectangle.alpha=1;
			sprite.addChild(this.history_rectangle);
		}
        
        /**
         * Looks for every onEnterFrame event if the user is scrubbing or not.
         * Throws a VideoPlayerTimeChangeEvent that moves the dragger to its new position.
         */        	
        private function onEnterFrame(event:Event):void
         {
         	try{
	         	if (this.duration<=0) return;
				drawHistoryRectangle()
	            scrubbingActions();
	
	            var test:String;		         
	            // Invokes moving the mouse pointer if MouseXML is available
	            if(locator.xmlParser.isMouseXMLAvailable())
	            {
	            	locator.defaultView.mousePointer_Component.visible=true;
	            	var tmpMouseStep:MouseStep = locator.xmlParser.getMouseStepByTime(locator.currentvideotime*1000);
	            	test=""+tmpMouseStep;
	            	
	            	locator.defaultView.moveMousePointer(tmpMouseStep.x,tmpMouseStep.y);
	            }
	            else
	            {		            	
	            	test="";
	            	locator.defaultView.mousePointer_Component.visible=false;
	            }	
	            durationLabel.text=test+" "+t.getTC(locator.currentvideotime)+"/"+ t.getTC(locator.metaData.duration);
         	}
         	catch(e:Error)
         	{	
         		trace("AdvancedScrubber. Error occured in onEnterFrame method! "+e);
         	}   
	    	var sprite:Sprite = this.thumb;
			if (sprite!=null){
				sprite.graphics.clear();
				sprite.alpha=1;
				sprite.graphics.beginFill(0x888888);   // Color, when mousepointer over thumb
				sprite.graphics.lineStyle(2,AS_Constants.DRAGGER_BORDER_COLOR);        
				handleScrub(sprite);  
			}       	      
		}     
	}
}